/* chimaera_group-table.c : store the group content
 *
 * ====================================================================
 * Copyright (c) 2008-2009 Chimaera team.  All rights reserved.
 *
 *
 * @author kkndyu
 * @mail kkndyu@gmail.com
 * ====================================================================
 */

#include "bdb_compat.h"
#include "svn_fs.h"
#include "svn_pools.h"
#include "../fs.h"
#include "../err.h"
#include "../util/skel.h"
#include "../util/fs_skels.h"
#include "../../libsvn_fs/fs-loader.h"
#include "bdb-err.h"
#include "dbt.h"
#include "rev-table.h"
#include "../trail.h"

#include "svn_private_config.h"
#include "private/svn_fs_util.h"

#include "chimaera_group-table.h"


/* Opening/creating the `chimaera_group' table.  */

int svn_fs_bdb__open_chimaera_group_table(DB **chimaeragroup_p,
                                     DB_ENV *env,
                                     svn_boolean_t create)
{
  const u_int32_t open_flags = (create ? (DB_CREATE | DB_EXCL) : 0);
  DB *chimaera_group;

  BDB_ERR(svn_fs_bdb__check_version());
  BDB_ERR(db_create(&chimaera_group, env, 0));
  BDB_ERR((chimaera_group->open)(SVN_BDB_OPEN_PARAMS(chimaera_group, NULL),
								"chimaera_group", 0, DB_RECNO,
								open_flags, 0666));

  *chimaeragroup_p = chimaera_group;
  return 0;
}



/* consider that is it necessary to sort the members in group
 * by recno, if sorted, the query will be fast.
 */


svn_error_t *
svn_fs_bdb__get_chimaera_group(apr_int32_t **chimaera_group,
						apr_int32_t *num, apr_int32_t recno_p, 
						svn_fs_t *fs, apr_pool_t *pool)
{
  base_fs_data_t *bfd = fs->fsap_data;
  int db_err;
  DBT key, value;
  db_recno_t recno = recno_p;
  apr_int32_t *first,*second;

  if (SVN_IS_VALID_REVNUM(recno_p))
  {
	  db_err = bfd->chimaera_group->get(bfd->chimaera_group, NULL,
		  svn_fs_base__set_dbt(&key, &recno,
		  sizeof(recno)),
		  svn_fs_base__result_dbt(&value),
		  0);
  }
  svn_fs_base__track_dbt(&value, pool);

  /* If there's no such node, return an appropriately specific error.  */
  if (db_err == DB_NOTFOUND)
	  return svn_error_createf
	  (SVN_ERR_FS_NO_SUCH_REPRESENTATION, 0,
	  _("No such chimaeragroup '%s'"), key);

  if (value.size!=0)
  {
	  first = value.data;
	  *num = value.size/sizeof(*first);

	  second = apr_palloc(pool,value.size);
	  memcpy(second,first,value.size);

	  *chimaera_group = second;
  }
  

  return SVN_NO_ERROR;
}

/* return value @a recno */
svn_error_t *
svn_fs_bdb__put_chimaera_group(svn_revnum_t *id,
			apr_int32_t *chimaeragroup,apr_int32_t num, 
			svn_fs_t *fs, DB_TXN *txn,apr_pool_t *pool)
{
  base_fs_data_t *bfd = fs->fsap_data;
  int db_err;
  db_recno_t recno = 0;
  DBT key, value;

  if (SVN_IS_VALID_REVNUM(*id))
  {
	  DBT query, result;

	  /* Update the filesystem revision with the new skel. */
	  recno = *id;
	  
	  svn_fs_base__set_dbt(&result, chimaeragroup, num*sizeof(*chimaeragroup));
	  db_err = bfd->chimaera_group->put
		  (bfd->chimaera_group, txn,
		  svn_fs_base__set_dbt(&query, &recno, sizeof(recno)),
		  &result, 0);
	  return BDB_WRAP(fs, "updating filesystem revision", db_err);
  }

  svn_fs_base__set_dbt(&value, chimaeragroup, num*sizeof(*chimaeragroup));

  db_err = bfd->chimaera_group->put(bfd->chimaera_group, txn,
	  svn_fs_base__recno_dbt(&key, &recno),
	  &value, DB_APPEND);
  SVN_ERR(BDB_WRAP(fs, "storing filesystem revision", db_err));

  /* if new insert, return the recno.  */
  *id = recno;
  return SVN_NO_ERROR;
}
